home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 5
/
MacMania 5.toast
/
/
Internet software
/
NewsWatcher
/
NW Source
/
Source
/
next.c
< prev
next >
Wrap
Text File
|
1997-01-09
|
14KB
|
502 lines
/*----------------------------------------------------------------------------
next.c
This module handles the next article, thread, and group commands.
Copyright © 1994-1997, Northwestern University.
----------------------------------------------------------------------------*/
#include <stdio.h>
#include "glob.h"
#include "article.h"
#include "newswatcher.h"
#include "mark.h"
#include "next.h"
#include "subject.h"
#include "dialog.h"
#include "dummy.h"
#include "help.h"
#include "group.h"
#include "biglist.h"
/*----------------------------------------------------------------------------
OpenNextUnreadGroup
Open the subject window for the next group with unread articles in a
group window.
Entry: wind = pointer to group window.
item = the item in the group list at which to start the
search for the next group with unread articles.
Exit: function result = error code.
----------------------------------------------------------------------------*/
static OSErr OpenNextUnreadGroup (WindowPtr wind, long item)
{
TWindow **info;
TGroupWindowKind groupKind;
TGroup **groupArray;
BigListRef groupList;
long index, numItems;
OSErr err = noErr;
Boolean hasArts;
info = (TWindow**)GetWRefCon(wind);
groupKind = (**info).groupKind;
groupArray = (**info).groupArray;
groupList = (**info).groupList;
numItems = BigLGetNumItems(groupList);
for (; item < numItems; item++) {
index = BigLGetData(groupList, item);
if ((groupKind == kUserGroup && (*groupArray)[index].unread != nil) ||
groupKind != kUserGroup)
{
BigLSelectOnlyOne(groupList, item);
BigLScrollItemIntoView(groupList, item, kBigLScrollToTop,
kBigLScrollToTop);
HandleUpdate(wind);
err = OpenGroupItem(wind, item, gPrefs.maxFetch, &hasArts);
if (err != noErr) return err;
if (err == noErr && hasArts) return noErr;
}
}
if (gPrefs.beepAtEndOfLists) SysBeep(0);
return noErr;
}
/*----------------------------------------------------------------------------
OpenNextUnreadArticle
Open the article window for the next unread article in a subject window.
Entry: wind = pointer to subject window.
item = the item in the subject list at which to start
the search for the next unread article.
threadOrdinal = ordinal of article within thread at which
to start the search if the item is a collapsed thread.
reuse = pointer to article window to be reused, or nil to
open new article window.
onlySelect = true to only select the next unrread article
in the subject window, but not open it.
Exit: function result = error code.
----------------------------------------------------------------------------*/
static OSErr OpenNextUnreadArticle (WindowPtr wind, long item,
long threadOrdinal, WindowPtr reuse, Boolean onlySelect)
{
TWindow **info;
TSubject **subjectArray;
BigListRef subjectList;
long numItems, index, i;
Boolean collapsed;
WindowPtr child, parent;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(wind);
subjectArray = (**info).subjectArray;
subjectList = (**info).subjectList;
numItems = BigLGetNumItems(subjectList);
while (item < numItems) {
index = BigLGetData(subjectList, item);
if (threadOrdinal > (*subjectArray)[index].threadLength) {
item++;
threadOrdinal = 1;
} else {
collapsed = (*subjectArray)[index].collapsed;
if (collapsed)
for (i = 1; i < threadOrdinal; i++)
index = (*subjectArray)[index].nextInThread;
if (!(*subjectArray)[index].read) {
BigLSelectOnlyOne(subjectList, item);
BigLScrollItemIntoView(subjectList, item, kBigLScrollToTop,
kBigLScrollToTop);
HandleUpdate(wind);
if (onlySelect) return noErr;
err = OpenSubjectItem(wind, item, threadOrdinal, reuse, &child);
if (err != noErr) return err;
if (child != nil) return noErr;
}
if (collapsed) {
threadOrdinal++;
} else {
item++;
threadOrdinal = 1;
}
}
}
if (reuse != nil) DoClose(reuse);
if (gPrefs.stopAtEndOfSubjectList) {
if (gPrefs.beepAtEndOfLists) SysBeep(0);
} else {
parent = (**info).parentWindow;
index = (**info).parentGroup;
err = DoClose(wind);
if (err != noErr) return err;
wind = parent;
item = FindParentItem(wind, index);
item++;
return OpenNextUnreadGroup(wind, item);
}
return noErr;
}
/*----------------------------------------------------------------------------
DoNextArticle
Handle the "Next Article" command.
Entry: wind = pointer to article, subject, or group window.
Exit: function result = error code.
----------------------------------------------------------------------------*/
OSErr DoNextArticle (WindowPtr wind)
{
TWindow **info;
WindowPtr parent;
long index, item, threadOrdinal;
TSubject **subjectArray, theSubject;
Boolean returnToSubjectWindow = false;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(wind);
switch ((**info).kind) {
case kArticle:
parent = (**info).parentWindow;
if (parent == nil) return noErr;
index = (**info).parentSubject;
info = (TWindow**)GetWRefCon(parent);
subjectArray = (**info).subjectArray;
theSubject = (*subjectArray)[index];
if (theSubject.collapsed) {
item = FindParentItem(parent, theSubject.threadHeadIndex);
threadOrdinal = theSubject.threadOrdinal + 1;
} else {
item = FindParentItem(parent, index);
item++;
threadOrdinal = 1;
}
if (gPrefs.returnToSubjectWindow) {
returnToSubjectWindow = true;
while (true) {
if (theSubject.threadOrdinal == theSubject.threadLength) break;
theSubject = (*subjectArray)[theSubject.nextInThread];
if (!theSubject.read) {
returnToSubjectWindow = false;
break;
}
}
}
if (returnToSubjectWindow) {
err = DoClose(wind);
if (err != noErr) return err;
return OpenNextUnreadArticle(parent, item, threadOrdinal, nil, true);
} else if (gPrefs.reuseArticleWinds) {
return OpenNextUnreadArticle(parent, item, threadOrdinal, wind, false);
} else {
err = DoClose(wind);
if (err != noErr) return err;
err = ShowDummyWindow();
if (err != noErr) return err;
err = OpenNextUnreadArticle(parent, item, threadOrdinal, nil, false);
HideDummyWindow();
return err;
}
case kSubject:
item = BigLGetFirstSelectedItem((**info).subjectList);
if (item < 0) item = 0;
threadOrdinal = 1;
return OpenNextUnreadArticle(wind, item, threadOrdinal, nil, false);
case kGroup:
item = BigLGetFirstSelectedItem((**info).groupList);
if (item < 0) item = 0;
return OpenNextUnreadGroup(wind, item);
}
return noErr;
}
/*----------------------------------------------------------------------------
DoNextThread
Handle the "Next Thread" command.
Entry: wind = pointer to article, subject, or group window.
Exit: function result = error code.
----------------------------------------------------------------------------*/
OSErr DoNextThread (WindowPtr wind)
{
TWindow **info;
WindowPtr parent;
long index, item;
TSubject **subjectArray, theSubject;
BigListRef subjectList;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(wind);
switch ((**info).kind) {
case kArticle:
parent = (**info).parentWindow;
if (parent == nil) return noErr;
index = (**info).parentSubject;
info = (TWindow**)GetWRefCon(parent);
subjectArray = (**info).subjectArray;
theSubject = (*subjectArray)[index];
MarkThread(parent, theSubject.threadHeadIndex, true);
item = FindParentItem(parent, theSubject.threadHeadIndex);
if (theSubject.collapsed) {
item++;
} else {
item += theSubject.threadLength;
}
if (gPrefs.reuseArticleWinds) {
return OpenNextUnreadArticle(parent, item, 1, wind, false);
} else {
err = DoClose(wind);
if (err != noErr) return err;
err = ShowDummyWindow();
if (err != noErr) return err;
err = OpenNextUnreadArticle(parent, item, 1, nil, false);
HideDummyWindow();
return err;
}
case kSubject:
subjectList = (**info).subjectList;
subjectArray = (**info).subjectArray;
item = BigLGetFirstSelectedItem(subjectList);
if (item >= 0) {
index = BigLGetData(subjectList, item);
theSubject = (*subjectArray)[index];
MarkThread(wind, theSubject.threadHeadIndex, true);
if (theSubject.collapsed) {
item++;
} else {
item += theSubject.threadLength + 1 - theSubject.threadOrdinal;
}
} else {
item = 0;
}
return OpenNextUnreadArticle(wind, item, 1, nil, false);
case kGroup:
item = BigLGetFirstSelectedItem((**info).groupList);
if (item < 0) item = 0;
return OpenNextUnreadGroup(wind, item);
}
return noErr;
}
/*----------------------------------------------------------------------------
DoNextGroup
Handle the "Next Group" command.
Entry: wind = pointer to article, subject, or group window.
Exit: function result = error code.
----------------------------------------------------------------------------*/
OSErr DoNextGroup (WindowPtr wind)
{
TWindow **info;
WindowPtr parent;
long item, index;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(wind);
switch ((**info).kind) {
case kArticle:
parent = (**info).parentWindow;
if (parent == nil) return noErr;
err = DoClose(wind);
if (err != noErr) return err;
wind = parent;
info = (TWindow**)GetWRefCon(wind);
/* fall through to kSubject case */;
case kSubject:
MarkAllSubjects(wind, true);
parent = (**info).parentWindow;
index = (**info).parentGroup;
err = DoClose(wind);
if (err != noErr) return err;
wind = parent;
item = FindParentItem(wind, index);
item++;
return OpenNextUnreadGroup(wind, item);
case kGroup:
item = BigLGetFirstSelectedItem((**info).groupList);
if (item < 0) item = 0;
return OpenNextUnreadGroup(wind, item);
}
return noErr;
}
/*----------------------------------------------------------------------------
OpenPrevOrNextArticle
Open the previous or next article.
Entry: parent = pointer to parent subject window.
item = the parent item in the subject window for the article.
threadOrdinal = ordinal of article within thread if thread
is collapsed, else 1.
reuse = pointer to article window to be reused, or nil to
open new article window.
dir = direction = -1 to open previous article, +1 to open
next article.
Exit: function result = error code.
----------------------------------------------------------------------------*/
static OSErr OpenPrevOrNextArticle (WindowPtr parent, long item,
long threadOrdinal, WindowPtr reuse, short dir)
{
TWindow **info;
TSubject **subjectArray;
BigListRef subjectList;
long numItems, index;
WindowPtr child;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(parent);
subjectArray = (**info).subjectArray;
subjectList = (**info).subjectList;
numItems = BigLGetNumItems(subjectList);
index = BigLGetData(subjectList, item);
while (true) {
if ((*subjectArray)[index].collapsed) {
threadOrdinal += dir;
if (threadOrdinal > (*subjectArray)[index].threadLength) {
item++;
if (item >= numItems) break;
threadOrdinal = 1;
index = BigLGetData(subjectList, item);
} else if (threadOrdinal <= 0) {
item--;
if (item < 0) break;
index = BigLGetData(subjectList, item);
if ((*subjectArray)[index].collapsed) {
threadOrdinal = (*subjectArray)[index].threadLength;
} else {
threadOrdinal = 1;
}
}
} else {
item += dir;
if (item >= numItems || item < 0) break;
index = BigLGetData(subjectList, item);
if (dir == -1 && (*subjectArray)[index].collapsed) {
threadOrdinal = (*subjectArray)[index].threadLength;
} else {
threadOrdinal = 1;
}
}
BigLSelectOnlyOne(subjectList, item);
BigLScrollItemIntoView(subjectList, item, kBigLScrollToTop,
kBigLScrollToTop);
HandleUpdate(parent);
err = OpenSubjectItem(parent, item, threadOrdinal, reuse, &child);
if (err != noErr) return err;
if (child != nil) return noErr;
}
SysBeep(0);
return noErr;
}
/*----------------------------------------------------------------------------
GoBackwardsOrForwardsOneArticle
Go backwards or forwards one article.
Entry: wind = pointer to article window.
dir = direction = -1 to go backwards, +1 to go forwards.
Exit: function result = error code.
----------------------------------------------------------------------------*/
OSErr GoBackwardsOrForwardsOneArticle (WindowPtr wind, short dir)
{
TWindow **info;
WindowPtr parent;
long index, item, threadOrdinal;
TSubject **subjectArray, theSubject;
Boolean returnToSubjectWindow = false;
OSErr err = noErr;
info = (TWindow**)GetWRefCon(wind);
if ((**info).kind != kArticle) return noErr;
parent = (**info).parentWindow;
if (parent == nil) return noErr;
index = (**info).parentSubject;
info = (TWindow**)GetWRefCon(parent);
subjectArray = (**info).subjectArray;
theSubject = (*subjectArray)[index];
if (theSubject.collapsed) {
item = FindParentItem(parent, theSubject.threadHeadIndex);
threadOrdinal = theSubject.threadOrdinal;
} else {
item = FindParentItem(parent, index);
threadOrdinal = 1;
}
if (gPrefs.reuseArticleWinds) {
err = OpenPrevOrNextArticle(parent, item, threadOrdinal, wind, dir);
} else {
err = DoClose(wind);
if (err != noErr) goto exit;
err = ShowDummyWindow();
if (err != noErr) goto exit;
err = OpenPrevOrNextArticle(parent, item, threadOrdinal, nil, dir);
HideDummyWindow();
}
exit:
KillBalloon();
return err;
}